package com.elitel.common.utils;

import com.alibaba.fastjson.JSON;
import com.elitel.frame.main.entity.CfgExtmaster;
import com.elitel.frame.main.entity.constant.DictionaryConstant;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.time.Year;
import java.util.*;

/**
 *
 * Only contain static method or immutable field
 *
 */
public final class XCommonUtils{

    // here is replace content
    public static final String OpenToken = "{{{";
    public static final String CloseToken = "}}}";
    public static final String OpenTokenInFreemarker = "'\\$\\{";
    public static final String CloseTokenInFreemarker = "}'";

    public static final SimpleDateFormat ChineseDateFormatToMillisecond = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    public static final SimpleDateFormat ChineseDateFormatToSecond = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static Set<String> filterRequestParam = new HashSet<String>();


    static{
        // here is set timezone question

        // 获取 “GMT+08:00”对应的时区
        //TimeZone china = TimeZone.getTimeZone("GMT+:08:00");
        // ChineseDateFormatToMillisecond.setTimeZone(china);
        // ChineseDateFormatToSecond.setTimeZone(china);

        filterRequestParam.add("serviceID");
        filterRequestParam.add("pageNO");
        filterRequestParam.add("pageSize");
        filterRequestParam.add("conQuery");
        filterRequestParam.add("refCache");
        filterRequestParam.add("_");
    }


    private XCommonUtils(){}

    // public static void main(String[] args){
    //     String sql = "'${xxxx}'";
    //     String modify = sql.replaceAll(OpenTokenInFreemarker, OpenToken).replaceAll(CloseTokenInFreemarker, CloseToken);
    //     System.out.println(modify);
    // }

    public static Date autoHandleDateTimeType(Object value) {
        // TODO 这个方法有问题

        if(!(value instanceof Date)){
            // auto parse date type
            String dateTime = value.toString().trim();

            // here is add current year
            // here is contain /
            if(dateTime.contains("/")){
                dateTime = dateTime.replaceAll("/", "-");
            }
            // digit 5: 12-31
            if(dateTime.length() == 5){
                Year year = Year.now();
                dateTime = year.toString() + "-" + dateTime;
            }
            // digit 10: 2022-12-31
            if(dateTime.length() == 10){
                dateTime += " 00:00:00.000";
            }
            // digit 16: 2022-12-32 10:37
            if(dateTime.length() == 16){
                dateTime += ":00.000";
            }
            // digit 19: 2022-12-31 10:37:00
            if(dateTime.length() == 19){
                dateTime += ".000";
            }
            // digit 23: 2022-12-31 10:37:00.000
            Date formatDateTime = parseChineseDateToMillisecond(dateTime);
            if(formatDateTime == null){
                System.out.println("auto parse date type is fail , value =" + value + " final convert dateTime: " + dateTime);
            }else{
                value = formatDateTime;
            }

        }
        return (Date)value;

    }

    public static Date parseChineseDateToMillisecond(String chineseDateContent){
        Date date = null;
        try{
            date = ChineseDateFormatToMillisecond.parse(chineseDateContent);
        }catch(Exception e){
        }
        return date;
    }

    public static String formatDateToMillisecond(Date date){
        if(date == null)
            return "";
        return ChineseDateFormatToMillisecond.format(date);
    }

    public static Date parseChineseDateToSecond(String chineseDateContent){
        Date date = null;
        try{
            date = ChineseDateFormatToSecond.parse(chineseDateContent);
        }catch(Exception e){
        }
        return date;
    }

    public static String formatDateToSecond(Date date){
        if(date == null)
            return "";
        return ChineseDateFormatToSecond.format(date);
    }



    public static String handleFreemakerSyntaxWithCutomToken(String originSql){
        if(isEmpty(originSql))
            return originSql;

        return originSql.replaceAll(OpenTokenInFreemarker, OpenToken).replaceAll(CloseTokenInFreemarker, CloseToken);
    }

    // here is provider return placeHolderOrderColumnObject order
    // but parse open token and close token can consist first replace
    // second read sql extract content
    // here is parse get order
    public static Map<String, String> extractPlaceHolderColumnObjectByParseSql(String originSql){
        Map<String, String> placeHolderOrderColumnObject = new LinkedHashMap<>();

        if(isEmpty(originSql))
            return placeHolderOrderColumnObject;

        String sqlWithCustomToken = XCommonUtils.handleFreemakerSyntaxWithCutomToken(originSql);
        String openToken = XCommonUtils.OpenToken;
        String closeToken = XCommonUtils.CloseToken;

        extractPlaceHolderColumnObject(sqlWithCustomToken, openToken, closeToken, placeHolderOrderColumnObject);

        // here is parse content and
        return placeHolderOrderColumnObject;
    }

    private static void extractPlaceHolderColumnObject(String sqlText, String openToken, String closeToken, Map<String, String> placeHolderOrderColumnObject){

        int openTokenIndex = sqlText.indexOf(openToken);
        int closeTokenIndex = sqlText.indexOf(closeToken);

        String content = "";
        String subSql = "";

        if(openTokenIndex != -1 && closeTokenIndex != -1){
            content = sqlText.substring(openTokenIndex + 3, closeTokenIndex).trim();
            subSql = sqlText.substring(closeTokenIndex + 3);
            // here is record
            placeHolderOrderColumnObject.put(content, null);
        }

        if(XCommonUtils.isEmpty(subSql))
            return;

        extractPlaceHolderColumnObject(subSql, openToken, closeToken, placeHolderOrderColumnObject);
    }


    public static boolean isEmpty(String content){
        return StringUtils.isEmpty(content);
    }

    public static boolean isNotEmpty(String content){
        return StringUtils.isNotEmpty(content);
    }

    public static boolean isEmpty(Map<?,?> map){
        return map == null || map.size() <= 0;
    }

    public static boolean isNotEmpty(Map<?,?> map){
        return !isEmpty(map);
    }

    public static boolean isEmpty(Collection<?> collection){
        return collection == null || collection.isEmpty();
    }

    public static boolean isNotEmpty(Collection<?>  collection){
        return !isEmpty(collection);
    }

    public static boolean isViewTableType(int tableType){
        return DictionaryConstant.TableType_View == tableType;
    }

    public static boolean isOriginSingleTableType(int tableType){
        return DictionaryConstant.TableType_OriginSingleTable == tableType;
    }

    public static boolean isJSONFieldEnumType(int fieldEnumType){
        return DictionaryConstant.FieldEnumType_JSON == fieldEnumType;
    }

    public static boolean isSQLFieldEnumType(int fieldEnumType){
        return DictionaryConstant.FieldEnumType_SQL == fieldEnumType;
    }

    public static boolean isFieldEnumType(String fieldEnumType){
        return (DictionaryConstant.FieldEnum + "").equals(fieldEnumType);
    }

    public static boolean isModifyNameForField(String baseFieldAddonsModifyName){
        return (DictionaryConstant.ModifyName + "").equals(baseFieldAddonsModifyName);
    }

    public static boolean isPageable(Short pagination){
        return pagination != null && DictionaryConstant.Pagination == pagination;
    }

    public static boolean isPageable(Integer pagination){
        return pagination != null && (int)DictionaryConstant.Pagination == pagination;
    }

    public static boolean isSingleTableService(String serviceType){
        return DictionaryConstant.SingleServiceInBaseQuerySql.equals(serviceType);
    }

    public static boolean isMasterSlaveTableService(String serviceType){
        return DictionaryConstant.MasterSlaveTableServiceInBaseQuerySql.equals(serviceType);
    }

    public static boolean isMasterService(String masterDetailId){
        return masterDetailId == null || DictionaryConstant.FindMasterTable.equals(masterDetailId);
    }

    public static boolean isSlaveService(String masterDetailId){
        return !isMasterService(masterDetailId);
    }

    public static boolean isResourceTreeService(String serviceType){
        return DictionaryConstant.ResourceTreeServiceInBaseQuerySql.equals(serviceType);
    }

    public static boolean isPreviewMode(String isPreview){
        return isNotEmpty(isPreview) && isPreview.equals("true");
    }

    public static boolean isSingleResponseMode(Integer responseMode){
        if(responseMode == null)
            return false;

        return responseMode == 1;
    }

    public static boolean isMultipleResponseMode(Integer responseMode){
        return !isSingleResponseMode(responseMode);
    }


    public static boolean isSingleResponseMode(CfgExtmaster extMaster){
        if(extMaster == null || extMaster.getResponseMode() == null)
            return false;

        return extMaster.getResponseMode() == 1;
    }

    public static boolean isMultipleResponseMode(CfgExtmaster extMaster){
        return !isSingleResponseMode(extMaster);
    }

    // here is provider find condition symbol
    public static String findConditionSymbol(String condition){
        if(condition.contains(" = "))           return " = ";
        else if (condition.contains(" != "))    return " != ";
        else if (condition.contains(" > "))     return " > ";
        else if (condition.contains(" >= "))    return " >= ";
        else if (condition.contains(" < "))     return " < ";
        else if (condition.contains(" <= "))    return " <= ";
        else if (condition.contains(" like "))  return " like ";
        else if (condition.contains(" in "))  return " in ";
        else                                    return " = ";
    }

    public static boolean isContainLeastOneString(String content, String... types){
        if(types == null)
            return false;

        for(String type : types){
            if(content.contains(type))
                return true;
        }

        return false;
    }

    // here is provider non boolean
    public static String concatRelativeOfBetweenTable(String relationType){
        switch (relationType) {
            case "1": // 内连接
                return " inner join ";
            case "2": // 左连接
                return " left join ";
            case "3": // 右连接
                return " right join ";
            default:
                return "";

        }
    }

    // here is convert to map from json string
    public static Map<String, Object> convertJsonStringToMap(String jsonString){
        if(isEmpty(jsonString))
            return new HashMap<>();

        return (Map)JSON.parse(jsonString);
    }


    public static boolean filterRequestParam(String paramName){
        return filterRequestParam.contains(paramName);
    }

    public static void P(Object content){
        System.out.println("luowen print object: " + content.toString());
    }
}
